import { ChangeEvent, createElement, HTMLAttributes, useCallback, useState, type FC } from 'react';
import classNames from 'classnames';

import { checkboxDefaultProps } from './defaultProps';
import type { CheckboxOptions } from './type';

export interface CheckboxProps extends CheckboxOptions, Omit<HTMLAttributes<HTMLDivElement>, 'id'> {}

const Checkbox: FC<CheckboxProps> = (props) => {
  const {
    className,
    ui,
    id,
    name,
    value,
    label,
    type,
    checked,
    defaultChecked,
    slider,
    toggle,
    readOnly,
    indeterminate,
    disabled,
    fitted,
    inverted,
    aligned,
    forwardedRef,
    ...checkboxProps
  } = props;

  const [isSubscribed, setIsSubscribed] = useState(checked);
  const [inputRef, setInputRef] = useState<HTMLInputElement | null>(null);
  const [indeterminated, setIndeterminated] = useState<boolean>(!!indeterminate);

  const inputRefFun = useCallback(
    (el: HTMLInputElement | null) => {
      if (el !== null) {
        el.indeterminate = indeterminated;
      }
      setInputRef(el);
    },
    [indeterminated],
  );

  const handleClick = () => {
    setIndeterminated(false);
    inputRef?.click();
  };

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    if (defaultChecked === undefined) {
      setIsSubscribed(e.target.checked);
    }
  };

  return createElement(
    'div',
    {
      ref: forwardedRef,
      className: classNames(
        { ui },
        {
          radio: type === 'radio',
          slider,
          toggle,
          'read-only': readOnly,
          checked: isSubscribed,
          disabled,
          fitted,
          inverted,
        },
        aligned,
        { aligned },
        'checkbox',
        { indeterminate },
        className,
      ),
      onClick: handleClick,
      ...checkboxProps,
    },
    [
      <input
        ref={inputRefFun}
        key="input"
        id={id && id !== '' ? id : undefined}
        className="hidden"
        type={type}
        name={name}
        checked={defaultChecked === undefined ? isSubscribed : undefined}
        tabIndex={0}
        onChange={handleChange}
        defaultChecked={defaultChecked}
        value={value}
        readOnly={readOnly}
        disabled={disabled}
      />,
      <label key="label" htmlFor={id && id !== '' ? id : undefined}>
        {label}
      </label>,
    ],
  );
};

Checkbox.displayName = 'Checkbox';
Checkbox.defaultProps = checkboxDefaultProps;

export default Checkbox;
